package cn.wolfcode.aspect;

import cn.wolfcode.domain.OperateLog;
import cn.wolfcode.mapper.OperateLogMapper;
import cn.wolfcode.util.JwtUtils;
import com.alibaba.fastjson.JSON;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;

@Component
@Aspect
public class OperateLogAspect {
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

/**
 * 环绕通知，用于处理带有@MyLog注解的方法
 * 通过ProceedingJoinPoint可以获取目标方法的详细信息
 * 并记录操作日志，包括操作用户、操作时间、类名、方法名、参数、返回值和执行时间
 *
 * @param pjp ProceedingJoinPoint，用于执行目标方法和获取目标方法信息
 * @return 目标方法的执行结果
 * @throws Throwable 目标方法可能抛出的异常
 */
    @Around("@annotation(cn.wolfcode.aspect.MyLog)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
    // 创建操作日志对象
        OperateLog operateLog = new OperateLog();
    // 从请求头中获取token并解析获取用户名
        String token = request.getHeader("token");
        String username = JwtUtils.parseJwt(token).get("username").toString();


    // 设置操作日志的基本信息
        operateLog.setOperateUser(username);        // 设置操作用户
        operateLog.setOperateTime(new Date());       // 设置操作时间
        operateLog.setClassName(pjp.getTarget().getClass().getName());  // 设置类名
        operateLog.setMethodName(pjp.getSignature().getName());        // 设置方法名
        operateLog.setArgs(Arrays.toString(pjp.getArgs()));            // 设置方法参数
    // 记录方法执行时间
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();              // 执行目标方法
        long end = System.currentTimeMillis();


    // 设置操作日志的返回值和执行耗时
        operateLog.setReturnValue(JSON.toJSONString(result));  // 设置返回值
        operateLog.setCostTime((int) (end - start));          // 设置耗时(毫秒)
    // 保存操作日志
        operateLogMapper.save(operateLog);
    // 返回目标方法的执行结果
        return result;

    }
}
